#include "Command.h"
#include "Accesser.h"
#include "qlogging.h"
#include "qdebug.h"

SINGLETON_INSTANCE(cmd_mgr);

cmd_Prop::cmd_Prop(Widget* w, const QString& name, const QString& value)
: QUndoCommand(QString("Attribute %1 %2").arg(name).arg(value))
{
    _widget = w;
    _name = name;
    _redo_value = value;
    _undo_value = Accesser::get(_widget, name);
}

void cmd_Prop::redo()
{
    Accesser::set(_widget, _name, _redo_value);
}

void cmd_Prop::undo()
{
    Accesser::set(_widget, _name, _undo_value);
}

cmd_Drag::cmd_Drag(std::map<Widget*, std::pair<CCPoint, CCPoint>>& m)
: QUndoCommand(QString("PosChanged [%1]").arg(m.size()))
{
    _map = m;
}

void cmd_Drag::redo()
{
    for (auto& it : _map)
    {
        it.first->setPosition(it.second.second);
    }
}

void cmd_Drag::undo()
{
    for (auto& it : _map)
    {
        it.first->setPosition(it.second.first);
    }
}

void cmd_mgr::add(QUndoCommand *cmd)
{
    cmd_Prop* last = dynamic_cast<cmd_Prop*>(_last);
    cmd_Prop* cur = dynamic_cast<cmd_Prop*>(cmd);

    if (cur)
    {
        if (!last)
        {
            _last = cmd;
            startMacro_(QString("CMD Group [%1]").arg(dynamic_cast<cmd_Prop*>(_last)->_name));
        }
        else if (last->_widget == cur->_widget && last->_name == cur->_name)
        {
        }
        else
        {
            _last = cmd;

            stopMacro_();
            startMacro_(QString("CMD Group [%1]").arg(dynamic_cast<cmd_Prop*>(_last)->_name));
        }
    }
    else if (last)
    {
        stopMacro_();
        _last = nullptr;
    }

    QUndoStack::push(cmd);
}

void cmd_mgr::undo_()
{
    if (_ismac)
        stopMacro_();
    if (QUndoStack::canUndo())
    {
        qDebug() << "undo" << command(index() - 1)->text();
        QUndoStack::undo();
    }
}

void cmd_mgr::redo_()
{
    if (QUndoStack::canRedo())
    {
        qDebug() << "redo" << command(index())->text();
        QUndoStack::redo();
    }
}

cmd_mgr::cmd_mgr()
{
    _last = nullptr;
    _ismac = false;
}

void cmd_mgr::startMacro_(const QString& name)
{
    qDebug() << "startMacro" << name;
    _ismac = true;
    beginMacro(name);
}

void cmd_mgr::stopMacro_()
{
    qDebug() << "endMacro";
    _ismac = false;
    endMacro();
}
